"""
结果 center路由模块
实现结果存储、查询、分享等接口
"""

# 添加项目根目录到Python路径
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# 导入FastAPI相关组件
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import JSONResponse, FileResponse
# 导入Pydantic模型用于数据验证
from pydantic import BaseModel
# 导入类型提示
from typing import List, Optional
# 导入SQLAlchemy会话
from sqlalchemy.orm import Session
# 导入JSON处理模块

# 导入模型和数据库会话
from utils.models import Result as ResultModel, ResultShare as ResultShareModel, get_db

# 创建API路由实例
router = APIRouter(
    prefix="/api/v1/results",  # 路由前缀
    tags=["results"],  # 标签
    responses={404: {"description": "Not found"}},  # 响应定义
)

# 数据模型定义
class ResultBase(BaseModel):
    """
    结果基础数据模型
    """
    name: str           # 结果名称
    workflow_id: int    # 关联的工作流ID
    data: dict          # 结果数据
    description: Optional[str] = None  # 结果描述

class ResultCreate(ResultBase):
    """
    结果创建数据模型
    """

class ResultUpdate(BaseModel):
    """
    结果更新数据模型
    """
    name: Optional[str] = None           # 结果名称
    data: Optional[dict] = None          # 结果数据
    description: Optional[str] = None    # 结果描述
    status: Optional[str] = None         # 结果状态
    is_public: Optional[int] = None      # 是否公开

class Result(ResultBase):
    """
    结果完整数据模型
    """
    id: int             # 结果ID
    user_id: int        # 关联的用户ID
    status: str         # 结果状态
    is_public: int      # 是否公开
    created_at: str     # 创建时间
    updated_at: str     # 更新时间

    class Config:
        from_attributes = True  # 启用ORM模式

class ResultResponse(BaseModel):
    """
    结果响应数据模型
    """
    message: str            # 响应消息
    result: Optional[Result] = None  # 结果数据

class ResultListResponse(BaseModel):
    """
    结果列表响应数据模型
    """
    message: str          # 响应消息
    results: List[Result] # 结果列表

class ShareResultRequest(BaseModel):
    """
    分享结果请求数据模型
    """
    shared_with: List[int]  # 分享给的用户ID列表
    permission: str         # 权限级别 ("read", "write")

class ShareResultResponse(BaseModel):
    """
    分享结果响应数据模型
    """
    message: str                    # 响应消息
    shared_result_id: int           # 分享结果ID
    shared_with_users: List[int]    # 分享给的用户ID列表

class DownloadResultResponse(BaseModel):
    """
    下载结果响应数据模型
    """
    message: str        # 响应消息
    download_url: str   # 下载链接

# 结果服务类
class ResultService:
    """
    结果服务类
    提供结果相关的业务逻辑处理
    """
    
    @staticmethod
    def result_to_dict(result: ResultModel) -> dict:
        """
        将数据库结果模型转换为字典
        Args:
            result (ResultModel): 数据库结果模型
        Returns:
            dict: 结果字典
        """
        return {
            "id": result.id,
            "name": result.name,
            "workflow_id": result.workflow_id,
            "user_id": result.user_id,
            "data": json.loads(result.data) if isinstance(result.data, str) else result.data,
            "status": result.status,
            "description": result.description,
            "is_public": result.is_public,
            "created_at": result.created_at.isoformat() if result.created_at else None,
            "updated_at": result.updated_at.isoformat() if result.updated_at else None
        }
    
    @staticmethod
    def dict_to_result_data(data: dict) -> str:
        """
        将字典转换为结果数据JSON字符串
        Args:
            data (dict): 结果数据字典
        Returns:
            str: JSON格式的数据字符串
        """
        return json.dumps(data)
    
    @staticmethod
    def export_result_data(result: ResultModel, format: str = "json") -> str:
        """
        导出结果数据到指定格式的文件
        Args:
            result (ResultModel): 结果模型
            format (str): 导出格式 ("json", "csv")
        Returns:
            str: 文件路径
        """
        try:
            # 确保导出目录存在
            export_dir = "./exports"
            os.makedirs(export_dir, exist_ok=True)
            
            # 生成文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"result_{result.id}_{timestamp}.{format}"
            file_path = os.path.join(export_dir, filename)
            
            # 获取结果数据
            data = json.loads(result.data) if isinstance(result.data, str) else result.data
            
            # 根据格式导出
            if format.lower() == "json":
                with open(file_path, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
            elif format.lower() == "csv":
                # 如果数据是列表形式，转换为DataFrame
                if isinstance(data, list):
                    df = pd.DataFrame(data)
                else:
                    # 如果是字典形式，包装成列表
                    df = pd.DataFrame([data])
                df.to_csv(file_path, index=False)
            else:
                raise ValueError(f"不支持的导出格式: {format}")
            
            return file_path
        except Exception as e:
            raise Exception(f"导出结果数据失败: {str(e)}")

# 路由定义
@router.get("/", response_model=ResultListResponse)
async def list_results(
    skip: int = 0, 
    limit: int = 100, 
    workflow_id: Optional[int] = None,
    status: Optional[str] = None,
    is_public: Optional[int] = None,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    获取结果列表接口
    从数据库获取结果列表
    Args:
        skip (int): 跳过的记录数
        limit (int): 限制返回的记录数
        workflow_id (int): 工作流ID筛选
        status (str): 状态筛选
        is_public (int): 是否公开筛选
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        ResultListResponse: 结果列表响应
    """
    # 构建查询
    query = db.query(ResultModel)
    
    # 添加筛选条件
    if workflow_id is not None:
        query = query.filter(ResultModel.workflow_id == workflow_id)
    
    if status is not None:
        query = query.filter(ResultModel.status == status)
    
    if is_public is not None:
        query = query.filter(ResultModel.is_public == is_public)
    
    # 如果不是管理员，只获取自己的结果或公开的结果
    # 这里简化处理，实际项目中应根据用户角色判断
    query = query.filter(
        (ResultModel.user_id == user_id) | (ResultModel.is_public == 1)
    )
    
    # 从数据库获取结果列表
    results = query.offset(skip).limit(limit).all()
    
    # 转换为响应格式
    result_list = [Result(**ResultService.result_to_dict(r)) for r in results]
    
    return {
        "message": "结果列表获取成功",
        "results": result_list
    }

@router.post("/", response_model=ResultResponse)
async def create_result(
    result: ResultCreate,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    创建结果接口
    将结果保存到数据库
    Args:
        result (ResultCreate): 结果创建信息
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        ResultResponse: 结果响应
    """
    # 创建结果记录
    db_result = ResultModel(
        name=result.name,
        workflow_id=result.workflow_id,
        user_id=user_id,
        data=ResultService.dict_to_result_data(result.data),
        description=result.description,
        status="completed"  # 默认状态为完成
    )
    
    # 保存到数据库
    db.add(db_result)
    db.commit()
    db.refresh(db_result)
    
    # 转换为响应格式
    result_dict = ResultService.result_to_dict(db_result)
    
    return {
        "message": "结果创建成功",
        "result": Result(**result_dict)
    }

@router.get("/{result_id}", response_model=ResultResponse)
async def get_result(
    result_id: int,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    获取结果详情接口
    从数据库获取指定结果的详细信息
    Args:
        result_id (int): 结果ID
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        ResultResponse: 结果响应
    Raises:
        HTTPException: 当结果未找到或无权限访问时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查访问权限（所有者或公开结果）
    if db_result.user_id != user_id and db_result.is_public != 1:
        # 检查是否被分享
        share_record = db.query(ResultShareModel).filter(
            ResultShareModel.result_id == result_id,
            ResultShareModel.shared_with_id == user_id
        ).first()
        
        if not share_record:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权限访问此结果"
            )
    
    # 转换为响应格式
    result_dict = ResultService.result_to_dict(db_result)
    
    return {
        "message": "结果获取成功",
        "result": Result(**result_dict)
    }

@router.put("/{result_id}", response_model=ResultResponse)
async def update_result(
    result_id: int,
    result: ResultUpdate,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    更新结果接口
    更新数据库中的结果信息
    Args:
        result_id (int): 结果ID
        result (ResultUpdate): 结果更新信息
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        ResultResponse: 结果响应
    Raises:
        HTTPException: 当结果未找到或无权限更新时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查更新权限（只有所有者可以更新）
    if db_result.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限更新此结果"
        )
    
    # 更新结果信息
    if result.name is not None:
        db_result.name = result.name
    if result.data is not None:
        db_result.data = ResultService.dict_to_result_data(result.data)
    if result.description is not None:
        db_result.description = result.description
    if result.status is not None:
        db_result.status = result.status
    if result.is_public is not None:
        db_result.is_public = result.is_public
    
    # 更新时间自动更新（由模型定义）
    
    # 保存到数据库
    db.commit()
    db.refresh(db_result)
    
    # 转换为响应格式
    result_dict = ResultService.result_to_dict(db_result)
    
    return {
        "message": "结果更新成功",
        "result": Result(**result_dict)
    }

@router.delete("/{result_id}")
async def delete_result(
    result_id: int,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    删除结果接口
    从数据库中删除指定的结果
    Args:
        result_id (int): 结果ID
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        dict: 删除成功信息
    Raises:
        HTTPException: 当结果未找到或无权限删除时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查删除权限（只有所有者可以删除）
    if db_result.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限删除此结果"
        )
    
    # 从数据库删除结果
    db.delete(db_result)
    db.commit()
    
    return {"message": f"结果 {result_id} 删除成功"}

@router.post("/{result_id}/share", response_model=ShareResultResponse)
async def share_result(
    result_id: int,
    request: ShareResultRequest,
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    分享结果接口
    实现结果分享逻辑
    Args:
        result_id (int): 结果ID
        request (ShareResultRequest): 分享请求信息
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        ShareResultResponse: 分享结果响应
    Raises:
        HTTPException: 当结果未找到或无权限分享时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查分享权限（只有所有者可以分享）
    if db_result.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限分享此结果"
        )
    
    # 创建分享记录
    shared_with_users = []
    for shared_user_id in request.shared_with:
        # 检查是否已存在分享记录
        existing_share = db.query(ResultShareModel).filter(
            ResultShareModel.result_id == result_id,
            ResultShareModel.shared_with_id == shared_user_id
        ).first()
        
        if not existing_share:
            # 创建新的分享记录
            share_record = ResultShareModel(
                result_id=result_id,
                sharer_id=user_id,
                shared_with_id=shared_user_id,
                permission=request.permission
            )
            db.add(share_record)
            shared_with_users.append(shared_user_id)
        else:
            # 更新已有的分享记录
            existing_share.permission = request.permission
            existing_share.updated_at = datetime.utcnow()
            db.commit()
            shared_with_users.append(shared_user_id)
    
    # 保存到数据库
    db.commit()
    
    return {
        "message": f"结果 {result_id} 分享成功",
        "shared_result_id": result_id,
        "shared_with_users": shared_with_users
    }

@router.get("/{result_id}/download")
async def download_result(
    result_id: int,
    format: str = "json",  # 导出格式，默认为json
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    下载结果接口
    实现结果下载逻辑
    Args:
        result_id (int): 结果ID
        format (str): 导出格式 ("json", "csv")
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        dict: 下载成功信息
    Raises:
        HTTPException: 当结果未找到或无权限下载时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查下载权限（所有者或公开结果）
    if db_result.user_id != user_id and db_result.is_public != 1:
        # 检查是否被分享
        share_record = db.query(ResultShareModel).filter(
            ResultShareModel.result_id == result_id,
            ResultShareModel.shared_with_id == user_id
        ).first()
        
        if not share_record:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权限下载此结果"
            )
    
    try:
        # 导出结果数据
        file_path = ResultService.export_result_data(db_result, format)
        
        # 返回下载链接
        return {
            "message": f"结果 {result_id} 下载准备完成",
            "download_url": f"/api/v1/results/{result_id}/download/file?format={format}"
        }
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"下载失败: {str(e)}"
        )

@router.get("/{result_id}/download/file")
async def download_result_file(
    result_id: int,
    format: str = "json",  # 导出格式，默认为json
    user_id: int = 1,  # 实际项目中应从认证信息中获取
    db: Session = Depends(get_db)
):
    """
    下载结果文件接口
    提供实际的文件下载
    Args:
        result_id (int): 结果ID
        format (str): 导出格式 ("json", "csv")
        user_id (int): 用户ID
        db (Session): 数据库会话
    Returns:
        FileResponse: 文件响应
    Raises:
        HTTPException: 当结果未找到或无权限下载时抛出异常
    """
    # 从数据库获取结果
    db_result = db.query(ResultModel).filter(ResultModel.id == result_id).first()
    
    # 检查结果是否存在
    if not db_result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="结果未找到"
        )
    
    # 检查下载权限（所有者或公开结果）
    if db_result.user_id != user_id and db_result.is_public != 1:
        # 检查是否被分享
        share_record = db.query(ResultShareModel).filter(
            ResultShareModel.result_id == result_id,
            ResultShareModel.shared_with_id == user_id
        ).first()
        
        if not share_record:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权限下载此结果"
            )
    
    try:
        # 导出结果数据
        file_path = ResultService.export_result_data(db_result, format)
        
        # 确定MIME类型
        media_type = "application/json" if format.lower() == "json" else "text/csv"
        
        # 返回文件响应
        return FileResponse(
            path=file_path,
            media_type=media_type,
            filename=f"result_{result_id}.{format}"
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"文件下载失败: {str(e)}"
        )